package com.yanqu.road.logic.cross;

import com.yanqu.road.dao.impl.cross.CrossGroupMonthRankDaoImpl;
import com.yanqu.road.entity.rank.cross.CrossUserRank;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.logic.helper.RankListHelper;
import com.yanqu.road.logic.pb.CrossRankPb;
import com.yanqu.road.logic.sort.CrossRankSort;
import com.yanqu.road.pb.rank.RankProto;

import java.math.BigInteger;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.IntStream;

public class CrossGroupMonthRankListModel {

    private int bigRankType;

    private int rankNum = GameConfig.UNION_PLAYER_MONTH_ABILITY_RANK_NUM_MAX;

    private CrossRankSort crossRankSort;

    private boolean isUpdate = false;

    private boolean isNeedSync = false;

    private LinkedList<CrossUserRank> rankList;
    private Map<Long, CrossUserRank> rankMap = new ConcurrentHashMap<>();

    private int rankType;

    private int groupId;

    private int month;

    private RankProto.RankListMsg.Builder rankListMsg;

    public CrossGroupMonthRankListModel(int groupId, int month, int bigRankType, int rankType) {
        crossRankSort = new CrossRankSort();
        rankList = new LinkedList<>();
        rankListMsg = RankProto.RankListMsg.newBuilder();
        this.groupId = groupId;
        this.month = month;
        this.bigRankType = bigRankType;
        this.rankType = rankType;
    }

    public int getBigRankType() {
        return bigRankType;
    }

    public int getGroupId() {
        return groupId;
    }

    public int getMonth() {
        return month;
    }

    public int getRankType() {
        return rankType;
    }

    public boolean isNeedSync() {
        return isNeedSync;
    }

    public void setNeedSync(boolean needSync) {
        isNeedSync = needSync;
    }

    public boolean isUpdate() {
        return isUpdate;
    }

    public void setUpdate(boolean update) {
        isUpdate = update;
    }

    public RankProto.RankListMsg.Builder getRankListMsg() {
        return rankListMsg;
    }

    public LinkedList<CrossUserRank> getRankList() {
        synchronized (this) {
            return new LinkedList<>(rankList);
        }
    }

    public void setRankList(LinkedList<CrossUserRank> userRankList) {
        synchronized (this) {
            rankList = new LinkedList<>(userRankList);
            RankListHelper.checkUserRankListValidEx(rankList);       //校验一下数组
            rankList.sort(crossRankSort);
            while (rankList.size() > rankNum) {
                rankList.removeLast();
            }
            initRankMsg();
        }
    }

    public void initRankMsg() {
        rankListMsg = CrossRankPb.parseRankListMsg(rankList);
    }

    public int getMyRank(long userId, long serverId) {
        synchronized (this) {
            OptionalInt result = IntStream.range(0, rankList.size()).filter(i -> rankList.get(i).getUserId() == userId &&
                    rankList.get(i).getUserBaseInfo().getServerId() == serverId).findFirst();
            if (result.isPresent()) {
                return result.getAsInt() + 1;
            }
            return -1;
        }
    }

    //排行固定了不会变化后用这个取排名
    public CrossUserRank getMyCrossUserRank(long userId, long serverId) {
        if (!rankList.isEmpty() && rankMap.isEmpty()){
            for (CrossUserRank crossUserRank : rankList) {
                rankMap.put(crossUserRank.getUserId(), crossUserRank);
            }
        }
        return rankMap.get(userId);
    }

    public LinkedList<CrossUserRank> removeRank(Set<Long> serverIdSet) {
        LinkedList<CrossUserRank> result = new LinkedList<>();
        synchronized (this) {
            Iterator<CrossUserRank> iterator = rankList.iterator();
            while (iterator.hasNext()) {
                CrossUserRank rank = iterator.next();
                if (!serverIdSet.contains(rank.getUserBaseInfo().getServerId())) {
                    if (rank.getValue().compareTo(BigInteger.ZERO) > 0) {
                        result.add(rank.clone());
                        rank.setValue(BigInteger.ZERO);
                        iterator.remove();    //策划需求要优化
                    }
                }
            }
            if (result.size() > 0) {
                rankList.sort(crossRankSort);
                initRankMsg();
                isUpdate = true;
                isNeedSync = true;
            }
        }
        return result;
    }

    /**
     * 添加到排行
     */
    public void rankChange(CrossUserRank crossUserRank, boolean isNeedUpdateMsg) {
        boolean isChange = false;
        synchronized (this) {
            int size = rankList.size();
            if (!rankList.stream().anyMatch(predicate -> predicate.getUserId() == crossUserRank.getUserId() &&
                    predicate.getUserBaseInfo().getServerId() == crossUserRank.getUserBaseInfo().getServerId())) {
                if (size < rankNum) {
                    CrossUserRank rank = crossUserRank.clone();
                    rank.setLastUpdateTime(System.currentTimeMillis() / 1000);
                    rankList.add(rank);
                    isChange = true;
                } else if (rankList.getLast().getValue().compareTo(crossUserRank.getValue()) < 0) {
                    replaceLastRank(crossUserRank);
                    isChange = true;
                }
            } else {
                rankList.forEach(action -> {
                    if (action.getUserId() == crossUserRank.getUserId() && action.getUserBaseInfo().getServerId() == crossUserRank.getUserBaseInfo().getServerId()) {
                        action.setUserBaseInfo(crossUserRank.getUserBaseInfo());
                        action.setValue(crossUserRank.getValue());
                        action.setLastUpdateTime(System.currentTimeMillis() / 1000);
                        action.setParam(crossUserRank.getParam());
                    }
                });
                isChange = true;
            }
            if (isChange) {
                rankList.sort(crossRankSort);
                isUpdate = true;
                isNeedSync = true;
            }
            if (isNeedUpdateMsg) {
                initRankMsg();
            }
        }
    }

    public void setRankNum(int rankNum) {
        this.rankNum = rankNum;
    }

    public void saveRankList() {
        LinkedList<CrossUserRank> newRankList;
        synchronized (this) {
            if (!isUpdate) {
                return;
            }
            newRankList = new LinkedList<>(rankList);
            isUpdate = false;
        }
        new CrossGroupMonthRankDaoImpl().updateCrossGroupMonthRankList(newRankList, groupId, month);
    }

    /**
     * 替换榜单最后一名
     */
    private CrossUserRank replaceLastRank(CrossUserRank crossUserRank) {
        CrossUserRank rank = rankList.getLast();
        rank.setUserId(crossUserRank.getUserId());
        rank.setUserBaseInfo(crossUserRank.getUserBaseInfo());
        rank.setValue(crossUserRank.getValue());
        rank.setLastUpdateTime(System.currentTimeMillis() / 1000);
        rank.setParam(crossUserRank.getParam());
        return rank;
    }

    public RankProto.RankListMsg.Builder getRankMsgByPagePara(int pageNo, int pageSize) {
        RankProto.RankListMsg.Builder msg = RankProto.RankListMsg.newBuilder();
        int beginRank = Math.max(pageNo * pageSize + 1, 1);
        int endRank = Math.min(beginRank + pageSize - 1, rankNum);
        // 超出榜单了，不返回
        if (beginRank > rankListMsg.getRankListList().size()) {
            return msg;
        }
        if (beginRank == 1 && endRank >= rankListMsg.getRankListList().size()) {
            return rankListMsg;
        }
        int rankNo = 0;
        for (CrossUserRank crossUserRank : rankList) {
            if (crossUserRank.getValue().equals(BigInteger.ZERO)){
                continue;
            }
            rankNo++;
            if (rankNo < beginRank) {
                continue;
            }
            if (rankNo > endRank) {
                break;
            }
            msg.addRankList(CrossRankPb.parseRankTempMsg(crossUserRank));
        }
        return msg;
    }

    public int getNowRankNum() {
        return rankList.size();
    }

    public void resetRankValue() {
        synchronized (this) {
            for (CrossUserRank crossUserRank : rankList) {
                crossUserRank.setValue(BigInteger.ZERO);
                crossUserRank.setParam("");
            }
            rankListMsg = RankProto.RankListMsg.newBuilder();
        }
    }

    public CrossUserRank getCrossUserRankByValue(BigInteger value) {
        if (rankList.isEmpty()){
            return null;
        }
        synchronized (this) {
            if (rankList.getLast().getValue().compareTo(value) >= 0) {
                return rankList.getLast();
            }
            for (CrossUserRank crossUserRank : rankList) {
                if (crossUserRank.getValue().compareTo(value) < 0) {
                    return crossUserRank;
                }
            }
        }
        return rankList.getLast();
    }

    public void addUserRank(CrossUserRank userRank){
        CrossUserRank rank = userRank.clone();
        if (!rankMap.containsKey(rank.getUserId())){
            rankList.add(rank);
            rankMap.put(rank.getUserId(), rank);
        }else{
            rankMap.get(rank.getUserId()).setValue(rank.getValue());
        }
    }

    public void endSort() {
        rankList.sort(crossRankSort);
        while (rankList.size() > rankNum) {
            rankList.removeLast();
        }
        rankMap.clear();
        for (int i = 0; i < rankList.size(); i++) {
            int rank = i + 1;
            rankList.get(i).setRank(rank);
            rankMap.put(rankList.get(i).getUserId(), rankList.get(i));
        }
        isUpdate = true;
        isNeedSync = true;
    }
}
